﻿//-----------------------------------------------------------------------
// <copyright>
//     Copyright (c) Artur Mustafin. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------

using System;

using Expressions.Compiler;

using Math.Compiler;

namespace Math.Compiler.Expressions
{
    internal static partial class ExpressionsDefinition
    {
        // Forward declarations
        internal static Expression<char, MathExpression> assigment_expression = "assigment-expression[t]";
        internal static Expression<char, MathExpression> reference = "reference[t]";
        internal static Expression<char, MathExpression> expression = "expression[t]";
        internal static Expression<char, MathExpression> expression_parameters = "expression-paremeters[t]";
        internal static Expression<char, MathExpression> function_definition = "function-definition[t]";
        internal static Expression<char, MathExpression> function_arg = "function-arg[t]";
        internal static Expression<char, MathExpression> function_arg_list = "function-arg-list[t]";
        internal static Expression<char, MathExpression> function_arg_list_part = "function-arg-list-part[t]";
        internal static Expression<char, MathExpression> E = "E[t]";
        internal static Expression<char, MathExpression> Eopt = "E'[t]";
        internal static Expression<char, MathExpression> T = "T[t]";
        internal static Expression<char, MathExpression> Topt = "T'[t]";
        internal static Expression<char, MathExpression> F = "F[t]";

        static ExpressionsDefinition()
        {
            E.Eval = _E();
            T.Eval = _T();
            Eopt.Eval = _Eopt();
            Topt.Eval = _Topt();
            F.Eval = _F();
            expression.Eval = _expression();
            expression_parameters.Eval = _expression_parameters();
            assigment_expression.Eval = _assigment_expression();
            function_definition.Eval = _function_definition();
            function_arg.Eval = (a, b) =>
            {
                if (b[0].Context.Token.Equals(NonterminalsDefinition.E))
                {
                    return E[a, b[0]];
                }
                throw new NotSupportedException("Input token is not supported");
            };
            function_arg_list.Eval = (a, b) =>
            {
                if (b[0].Context.Token.Equals(NonterminalsDefinition.function_arg) && (b[1] == null || b[1].Context.Token.Equals(NonterminalsDefinition.function_arg_list_part)))
                {
                    return new Parameter(function_arg[a, b[0]], function_arg_list_part[a, b[1]]);
                }
                throw new NotSupportedException("Input token is not supported");
            };
            function_arg_list_part.Eval = (a, b) =>
            {
                if (b[0].Context.Token.Equals(',') && b[1].Context.Token.Equals(NonterminalsDefinition.function_arg_list))
                {
                    return function_arg_list[a, b[1]];
                }
                throw new NotSupportedException("Input token is not supported");
            };
            reference.Eval = (a, b) =>
            {
                if (b[0].Context.Token.Equals(NonterminalsDefinition.alpha_digits) && b[1].Context.Token.Equals(NonterminalsDefinition.decimal_digits))
                {
                    return new VariableReference(b[0].Context.ToString() + b[1].Context.ToString());
                }
                throw new NotSupportedException("Input token is not supported");
            };
        }
    }
}